#include <gflags/gflags.h>
#include <gtest/gtest.h>

#include "logger.hpp"
#include "channel.hpp"
#include "etcd.hpp"
#include "utils.hpp"

#include "user-odb.hxx"
#include "base.pb.h"
#include "file.pb.h"
#include "user.pb.h"

DEFINE_bool(run_mode, true, "是否为调试模式");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志输出等级");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(user_service, "/service/user_service", "服务监控根目录");

class UserClientTest: public testing::Test{
    protected:
    void SetUp() override{
        // 绑定 RPC 信道
        auto sm = std::make_shared<im::ServiceManager>();
        sm->declared(FLAGS_user_service);
        auto put_cb = std::bind(&im::ServiceManager::onServiceOnline, sm.get(), std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&im::ServiceManager::onServiceOffline, sm.get(), std::placeholders::_1, std::placeholders::_2);
        // 初始化服务发现
        im::Discover::ptr dclient = std::make_shared<im::Discover>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);
        channel = sm->choose(FLAGS_user_service);
        if (!channel) {
            im::LOG_CRITICAL("Failed to get RPC channel");
        }
        // 测试数据 -- mysql数据库里存在该用户
        user_info.set_nickname("猪爸爸");
        user_info.set_user_id("1d56-513d8e49-0002");
        user_info.set_description("这是一个强大的猪爸爸");
        user_info.set_phone("15929917272");
        user_info.set_avatar("dummy_avatar_data");
    }
    
    void TearDown() override{
        // 清理资源
    }

    im::ServiceChannel::ChannelPtr channel;
    std::string login_ssid;
    im::UserInfo user_info;
};

// // 测试用户注册
// TEST_F(UserClientTest, TestUserRegisterSuccess){
//     im::UserService_Stub stub(channel.get());
//     im::UserRegisterReq req;
//     std::string uuid = im::uuid();
//     req.set_request_id(uuid);
//     req.set_nickname("zhangsan");
//     req.set_password("123123");

//     im::UserRegisterRsp rsp;
//     brpc::Controller cntl;
//     stub.UserRegister(&cntl, &req, &rsp, nullptr);

//     ASSERT_FALSE(cntl.Failed());
//     ASSERT_EQ(rsp.request_id(), uuid);
//     ASSERT_TRUE(rsp.success());
//     ASSERT_EQ(rsp.errmsg(), "");
// }

// 测试用户注册（非法用户名）
TEST_F(UserClientTest, TestUserRegisterInvalidName) {
    im::UserService_Stub stub(channel.get());
    im::UserRegisterReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    req.set_nickname("this_is_a_very_long_invalid_username");
    req.set_password("123456");

    im::UserRegisterRsp rsp;
    brpc::Controller cntl;
    stub.UserRegister(&cntl, &req, &rsp, nullptr);

    ASSERT_EQ(rsp.request_id(), uuid);
    ASSERT_FALSE(rsp.success());
    ASSERT_EQ(rsp.errmsg(), "用户名长度不合法!");
}

// 测试用户登录
TEST_F(UserClientTest, TestUserLoginSuccess) {
    im::UserService_Stub stub(channel.get());
    im::UserLoginReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    req.set_nickname("zhangsan");
    req.set_password("123123");

    im::UserLoginRsp rsp;
    brpc::Controller cntl;
    stub.UserLogin(&cntl, &req, &rsp, nullptr);

    ASSERT_TRUE(rsp.success());
    ASSERT_FALSE(rsp.login_session_id().empty());
    login_ssid = rsp.login_session_id();
}


// // 测试获取短信验证码
// TEST_F(UserClientTest, TestGetPhoneVerifyCode) {
//     im::UserService_Stub stub(channel.get());
//     im::PhoneVerifyCodeReq req;
//     std::string uuid = im::uuid();
//     req.set_request_id(uuid);
//     req.set_phone_number("13812345678"); // 合法手机号

//     im::PhoneVerifyCodeRsp rsp;
//     brpc::Controller cntl;
//     stub.GetPhoneVerifyCode(&cntl, &req, &rsp, nullptr);

//     ASSERT_EQ(rsp.request_id(), uuid);
//     ASSERT_TRUE(rsp.success());
//     ASSERT_FALSE(rsp.verify_code_id().empty());
// }

// // 测试手机号注册
// TEST_F(UserClientTest, TestPhoneRegisterSuccess) {
//     im::UserService_Stub stub(channel.get());
//     im::PhoneRegisterReq req;
//     std::string uuid = im::uuid();
//     req.set_request_id(uuid);
//     req.set_phone_number("13987654321");
//     req.set_verify_code_id("test_code_id");
//     req.set_verify_code("1234"); // 假设redis中已预存该验证码

//     im::PhoneRegisterRsp rsp;
//     brpc::Controller cntl;
//     stub.PhoneRegister(&cntl, &req, &rsp, nullptr);

//     ASSERT_EQ(rsp.request_id(), uuid);
//     ASSERT_TRUE(rsp.success());
// }

// 测试设置用户头像
TEST_F(UserClientTest, TestSetUserAvatar) {
    im::UserService_Stub stub(channel.get());
    im::SetUserAvatarReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    req.set_user_id(user_info.user_id());
    req.set_avatar("dummy_avatar_data");

    im::SetUserAvatarRsp rsp;
    brpc::Controller cntl;
    stub.SetUserAvatar(&cntl, &req, &rsp, nullptr);

    ASSERT_EQ(rsp.request_id(), uuid);
    ASSERT_TRUE(rsp.success());
    // im::LOG_DEBUG("生成的头像ID:{}", rsp.ava)
}

// 测试设置用户昵称
TEST_F(UserClientTest, TestSetUserNickname) {
    im::UserService_Stub stub(channel.get());
    im::SetUserNicknameReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    req.set_user_id(user_info.user_id());
    req.set_nickname("猪爸爸");

    im::SetUserNicknameRsp rsp;
    brpc::Controller cntl;
    stub.SetUserNickname(&cntl, &req, &rsp, nullptr);

    ASSERT_EQ(rsp.request_id(), uuid);
    ASSERT_TRUE(rsp.success());
}

// 测试设置用户签名
TEST_F(UserClientTest, TestSetUserDescription) {
    im::UserService_Stub stub(channel.get());
    im::SetUserDescriptionReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    req.set_user_id(user_info.user_id());
    req.set_description("这是一个强大的猪爸爸");

    im::SetUserDescriptionRsp rsp;
    brpc::Controller cntl;
    stub.SetUserDescription(&cntl, &req, &rsp, nullptr);

    ASSERT_EQ(rsp.request_id(), uuid);
    ASSERT_TRUE(rsp.success());
}

// 测试获取用户信息
TEST_F(UserClientTest, TestGetUserInfo) {
    im::UserService_Stub stub(channel.get());
    im::GetUserInfoReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    req.set_user_id(user_info.user_id());// 数据库里存在该用户
    req.set_session_id(login_ssid);

    im::GetUserInfoRsp rsp;
    brpc::Controller cntl;
    stub.GetUserInfo(&cntl, &req, &rsp, nullptr);

    ASSERT_FALSE(cntl.Failed());
    ASSERT_EQ(rsp.request_id(), uuid);
    ASSERT_TRUE(rsp.success());
    ASSERT_TRUE(rsp.has_user_info());

    EXPECT_EQ(user_info.user_id(), rsp.user_info().user_id());
    EXPECT_EQ(user_info.nickname(), rsp.user_info().nickname());
    EXPECT_EQ(user_info.description(), rsp.user_info().description());
    EXPECT_EQ(user_info.phone(), rsp.user_info().phone());
    EXPECT_EQ(user_info.avatar(), rsp.user_info().avatar());
}


// 测试批量获取用户信息
TEST_F(UserClientTest, TestGetMultiUserInfo) {
    im::UserService_Stub stub(channel.get());
    im::GetMultiUserInfoReq req;
    std::string uuid = im::uuid();
    req.set_request_id(uuid);
    std::vector<std::string> vuid{"b3a6-96f15f76-0000",user_info.user_id()};
    for(int i = 0; i < vuid.size(); ++i)
        req.add_users_id(vuid[i]);

    im::GetMultiUserInfoRsp rsp;
    brpc::Controller cntl;
    stub.GetMultiUserInfo(&cntl, &req, &rsp, nullptr);

    ASSERT_EQ(rsp.request_id(), uuid);
    ASSERT_TRUE(rsp.success());
    ASSERT_EQ(rsp.users_info_size(), vuid.size());

    auto user_map = rsp.users_info();

    EXPECT_EQ(user_map[vuid[0]].user_id(), vuid[0]);
    EXPECT_EQ(user_map[vuid[0]].nickname(), "zhangsan");
    EXPECT_EQ(user_map[vuid[0]].description(), "");
    EXPECT_EQ(user_map[vuid[0]].phone(), "");
    EXPECT_EQ(user_map[vuid[0]].avatar(), "");

    EXPECT_EQ(user_map[vuid[1]].user_id(), user_info.user_id());
    EXPECT_EQ(user_map[vuid[1]].nickname(), user_info.nickname());
    EXPECT_EQ(user_map[vuid[1]].description(), user_info.description());
    EXPECT_EQ(user_map[vuid[1]].phone(), user_info.phone());
    EXPECT_EQ(user_map[vuid[1]].avatar(), user_info.avatar());
}

int main(int argc, char *argv[]) {
    testing::InitGoogleTest(&argc, argv);
    google::ParseCommandLineFlags(&argc, &argv, true);
    im::initLogger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    return RUN_ALL_TESTS();
}